<?php
/**
 * 
 * @author	ronnie  (comdeng@gmail.com)
 * @link		http://fillphp.com/
 * @date		2014-5-1 上午1:13:12
 * @file		Dispatch.php
 * @description 
 */
namespace fillphp;

require_once __DIR__.'/page/Response.php';
require_once __DIR__.'/page/Controller.php';
require_once __DIR__.'/hook/Hook.php';


// set_exception_handler(function($ex){
// 	print_r($ex);
// });

class BlankDispatch
{
	const CONTROLLER_FILENAME = 'BlankController.php';
	const CONTROLLER_CLASSNAME = 'BlankController';
	
	/**
	 * 分配
	 * @param string $url
// 	 * @param \fillphp\page\Request $curReq 当前请求
	 * @throws \Exception
	 */
	function dispatch($uri)
	{
		require_once __DIR__.'/page/Request.php';
		$request = \fillphp\page\Request::build($uri);
		
		$arr = explode('/', rtrim( ltrim(strtolower($request->url), '/'), '/') );
		$len = count($arr);
		// 网址必须有至少有两截，能明确指定controller和action
		if ($len < 2) {
			throw new \Exception('\fillphp\blank_dispatch\urlIllegal');
		}
		$method = array_pop($arr).'Action';
		$file = sprintf('%s/%s/%s', PAGE_ROOT, implode('/', $arr), self::CONTROLLER_FILENAME);
		
		if (!is_readable($file)) {
			throw new \Exception('\fillphp\blank_dispatch\controllerNotFound file:'.$file);
		}
		
		require_once $file;
		$className = sprintf('%s\%s%s', NAMESPACE_ROOT."\\page", ($arr ? implode("\\", $arr)."\\" : ''), self::CONTROLLER_CLASSNAME);
		if (!class_exists($className)) {
			throw new \Exception('\fillphp\blank_dispatch\classNotDefined class:'.$className);
		}
		$action = new $className;
		if (!is_callable(array($action, $method))) {
			throw new \Exception('\fillphp\blank_dispatch\methodNotCallable method:'.$method);
		}
		
		// 构建传入的参数, 优先使用和参数中同名的gets变量，而不是通过url传入的参数
		$refMethod = new \ReflectionMethod($action, $method);
		$params = $refMethod->getParameters();
		$ps = array();
		foreach($params as $key => $param) {
			$name = $param->getName();
			if (isset($request->inputs['gets'][$name])) {
				$ps[] = $request->inputs['gets'][$name];
			} else {
				if ($param->isDefaultValueAvailable()) {
					$ps[] = $param->getDefaultValue();
				} else {
					throw new \Exception('\fillphp\blank_dispatch\paramNotDefined param:'.$name);
				}
			}
		}
		// 设置action的request对象
		$action->setRequest($request);
		
		$response = $refMethod->invokeArgs($action, $ps);
		if (!$response instanceof \fillphp\page\Response) {
			throw new \Exception('\fillphp\dispatch\responseClassIllegal');
		}
		return $response->content;
	}
}